package research.ui.editors;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.forms.widgets.TableWrapData;

import research.domain.Sample;
import research.domain.Test;
import research.domain.TestParameter;
import research.domain.TestParameterValue;
import research.domain.TestType;
import research.entity.Entity;
import research.entity.EntityFactory;
import research.entity.EntityType;
import research.model.EntityListContentProvider;
import research.model.ListHierarchy;
import research.model.TestHierarchy;
import research.model.TestTypeHierarchy;
import research.persistence.PersistenceManager;
import research.ui.editors.input.EntityEditorInput;
import research.ui.editors.tableeditors.test.TestTableEditor;

public class TestEditor extends FormEntityEditor {
	public static String ID = "research.ui.editors.TestEditor";
	private Text description;
	private TestTableEditor valuesEditor;
	private ComboViewer sample;
	private ComboViewer testType;
	private List<Entity> values;
	private List<Entity> initValues;
	
	private Test getEntity() {
		return (Test) entity;
	}

	@Override
	protected boolean checkInputEntityType(EntityEditorInput input) {
		return input.getEntity().getType().equals(EntityType.Test);
	}

	@Override
	protected void fill() {
		setComboEntity(sample, this.getEntity().getSample());
		setComboEntity(testType, this.getEntity().getTestType());
		
		this.description.setText(this.getEntity().getDescription());
		
		updateTable(values);
	}

	@Override
	protected void initialize() {
		if (!isNewEntity()) {
			values = PersistenceManager.getInstance().getDataSource().getChildren(getEntity(), new TestHierarchy());
		} else {
			values = new ArrayList<Entity>();
		}
		
		initValues = new ArrayList<Entity>(values);
	}
	
	@Override
	protected void persist() {
		
		for (Entity oldpar : initValues) {
			if (!valuesEditor.getEntityList().getEntities().contains(oldpar)) {
				getPersistenceManager().remove(oldpar);
			}
		}

		for (Entity par : valuesEditor.getEntityList().getEntities()) {
			TestParameterValue val = (TestParameterValue) par;
			if (!Double.isNaN(val.getValue())) {
				val.setTest(getEntity());
				getPersistenceManager().persist(val);
			}
		}
	}

	@Override
	protected boolean readAndValidate() {
		this.getEntity().setDescription(this.description.getText());
		
		Sample cal = (Sample) getComboEntity(sample);
		TestType type = (TestType) getComboEntity(testType);

		if (cal == null) {
			MessageDialog.openWarning(getSite().getShell(), "Error",
					"Выберите образец");
			return false;
		}
		
		if (type == null) {
			MessageDialog.openWarning(getSite().getShell(), "Error",
					"Выберите тип испытания");
			return false;
		}
		
		this.getEntity().setSample(cal);
		this.getEntity().setTestType(type);

		return true;
	}

	@Override
	protected void renderForm() {
		TableWrapData td;
		Section section;
		Composite composite;
		GridData gd;
		
		/*
		 * Sample
		 */
		section = toolkit.createSection(form.getBody(), Section.TITLE_BAR);
		td = new TableWrapData(TableWrapData.FILL);
		section.setLayoutData(td);
		section.setText("Испытание");
		composite = toolkit.createComposite(section);
		composite.setLayout(new GridLayout(2, false));
		section.setClient(composite);
		gd = new GridData();
		Label label = toolkit.createLabel(composite, "Выберите образец*:");
		label.setLayoutData(gd);
		gd = new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_HORIZONTAL);
		sample = new ComboViewer(composite, SWT.DROP_DOWN
				| SWT.READ_ONLY);
		sample.setContentProvider(new EntityListContentProvider(new ListHierarchy(EntityType.Sample), false));
		sample.setLabelProvider(new LabelProvider());
		sample.setInput(PersistenceManager.getInstance());
		gd.widthHint = 100;
		sample.getCombo().setLayoutData(gd);
		sample.getCombo().addModifyListener(getTextModifyListener());
		
		/*
		 * Test Type
		 */
		gd = new GridData();
		label = toolkit.createLabel(composite, "Выберите тип*:");
		label.setLayoutData(gd);
		gd = new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_HORIZONTAL);
		testType = new ComboViewer(composite, SWT.DROP_DOWN
				| SWT.READ_ONLY);
		testType.setContentProvider(new EntityListContentProvider(new ListHierarchy(EntityType.TestType), false));
		testType.setLabelProvider(new LabelProvider());
		testType.setInput(PersistenceManager.getInstance());
		gd.widthHint = 100;
		testType.getCombo().setLayoutData(gd);
		testType.getCombo().addModifyListener(getTextModifyListener());
		
		/*
		 * Description
		 */
		section = toolkit.createSection(form.getBody(), Section.TITLE_BAR);
		td = new TableWrapData(TableWrapData.FILL_GRAB);
		section.setLayoutData(td);
		section.setText("Описание");
		composite = toolkit.createComposite(section);
		composite.setLayout(new GridLayout(1, false));
		section.setClient(composite);
		gd = new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_HORIZONTAL);
		description = toolkit.createText(composite, "",
				SWT.BORDER | SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
		gd.widthHint = 200;
		gd.heightHint = 60;
		description.setLayoutData(gd);
		description.addModifyListener(getTextModifyListener());
		
		/*
		 * Test Parameters Values
		 */
		section = toolkit.createSection(form.getBody(), Section.TITLE_BAR
				| Section.TWISTIE | Section.EXPANDED);
		td = new TableWrapData(TableWrapData.FILL);
		td.heightHint = 300;
		section.setLayoutData(td);
		section.setText("Результаты измерений");
		composite = toolkit.createComposite(section);
		section.setClient(composite);
		valuesEditor = new TestTableEditor(composite);

		testType.getCombo().addModifyListener(new TestModifyListener());

	}
	
	private void updateTable(List<Entity> values) {
		List<Entity> parameters = new ArrayList<Entity>();
		TestType cal = (TestType) ((StructuredSelection)testType.getSelection()).getFirstElement();
		if (cal != null) {
			parameters = PersistenceManager.getInstance().getDataSource().getChildren(cal, new TestTypeHierarchy());
		}

		List<Entity> input = new ArrayList<Entity>();
		for (Entity param : parameters) {
			TestParameter p = (TestParameter) param;
			TestParameterValue value = null;
			for (Entity v : values) {
				if (((TestParameterValue) v).getTestParameter().equals(p))
					value = (TestParameterValue) v;
			}
			
			if (value == null) {
				value = (TestParameterValue) EntityFactory.getNew(EntityType.TestParameterValue);
				value.setTestParameter(p);
				value.setValue(Double.NaN);
			}
			
			input.add(value);
		}
		
		valuesEditor.setInput(input);
		valuesEditor.addModifyListener(getEntityTableListener());
	}
	
	public class TestModifyListener implements ModifyListener {
		@Override
		public void modifyText(ModifyEvent e) {
			updateTable(new ArrayList<Entity>());
		}
	}

}
